Build a CommandPrototype instead of a ProcessBuilder
authorPierre Krieger <pierre.krieger1708@gmail.com>
Tue, 30 Dec 2014 17:15:44 +0000 (18:15 +0100)
committerPierre Krieger <pierre.krieger1708@gmail.com>
Sun, 4 Jan 2015 10:53:02 +0000 (11:53 +0100)
15 files changed:
src/bin/bench.rs
src/bin/build.rs
src/bin/doc.rs
src/bin/run.rs
src/bin/test.rs
src/cargo/ops/cargo_compile.rs
src/cargo/ops/cargo_package.rs
src/cargo/ops/cargo_run.rs
src/cargo/ops/cargo_rustc/compilation.rs
src/cargo/ops/cargo_rustc/context.rs
src/cargo/ops/cargo_rustc/custom_build.rs
src/cargo/ops/cargo_rustc/engine.rs [new file with mode: 0644]
src/cargo/ops/cargo_rustc/mod.rs
src/cargo/ops/cargo_test.rs
src/cargo/ops/mod.rs

index 67fefb66e1c01ea7aa81fdfd8ea8be61c000be21..ac591a677b23c8992ad322226a199ccb5cc97766 100644 (file)
@@ -63,7 +63,8 @@ pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>
             features: options.flag_features.as_slice(),
             no_default_features: options.flag_no_default_features,
             spec: options.flag_package.as_ref().map(|s| s.as_slice()),
-            lib_only: false
+            lib_only: false,
+            exec_engine: None,
         },
     };
 
index edd100685ec1790d9a5edc2e931384b00be14735..aafd93bff90489fbdcee32bac5db9948e314f7a3 100644 (file)
@@ -64,7 +64,8 @@ pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>
         features: options.flag_features.as_slice(),
         no_default_features: options.flag_no_default_features,
         spec: options.flag_package.as_ref().map(|s| s.as_slice()),
-        lib_only: options.flag_lib
+        lib_only: options.flag_lib,
+        exec_engine: None,
     };
 
     ops::compile(&root, &mut opts).map(|_| None).map_err(|err| {
index 78be47183772d803edecd105798cbadc9c9bd76b..28c273380807bb0d76fc79cbfdf4ebf583ba6cd3 100644 (file)
@@ -58,7 +58,8 @@ pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>
             features: options.flag_features.as_slice(),
             no_default_features: options.flag_no_default_features,
             spec: options.flag_package.as_ref().map(|s| s.as_slice()),
-            lib_only: false
+            lib_only: false,
+            exec_engine: None,
         },
     };
 
index 29265d49d3ab29ed257eb10b30837a38ab95deed..9883e5c044a92b603d02d56a7f5009c352bce558 100644 (file)
@@ -67,7 +67,8 @@ pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>
         features: options.flag_features.as_slice(),
         no_default_features: options.flag_no_default_features,
         spec: None,
-        lib_only: false
+        lib_only: false,
+        exec_engine: None,
     };
 
     let (target_kind, name) = match (options.flag_bin, options.flag_example) {
index 7f4e950c12d1f03f3ff2f8905cfc0a86b2643146..26a3346dc0f76605ae658b3341a68be2b8ef3e19 100644 (file)
@@ -65,7 +65,8 @@ pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>
             features: options.flag_features.as_slice(),
             no_default_features: options.flag_no_default_features,
             spec: options.flag_package.as_ref().map(|s| s.as_slice()),
-            lib_only: false
+            lib_only: false,
+            exec_engine: None,
         },
     };
 
index ec30b63ba3a79ca75da9743fc65bd1b163d71c35..1646b651755ddb58494914c534a733ab7e003d8e 100644 (file)
 use std::os;
 use std::collections::HashMap;
 use std::default::Default;
+use std::sync::Arc;
 
 use core::registry::PackageRegistry;
 use core::{MultiShell, Source, SourceId, PackageSet, Package, Target, PackageId};
 use core::resolver::Method;
-use ops::{mod, BuildOutput};
+use ops::{mod, BuildOutput, ExecEngine};
 use sources::{PathSource};
 use util::config::{Config, ConfigValue};
 use util::{CargoResult, config, internal, human, ChainError, profile};
@@ -47,7 +48,8 @@ pub struct CompileOptions<'a> {
     pub features: &'a [String],
     pub no_default_features: bool,
     pub spec: Option<&'a str>,
-    pub lib_only: bool
+    pub lib_only: bool,
+    pub exec_engine: Option<Arc<Box<ExecEngine>>>,
 }
 
 pub fn compile(manifest_path: &Path,
@@ -72,7 +74,8 @@ pub fn compile_pkg(package: &Package, options: &mut CompileOptions)
                    -> CargoResult<ops::Compilation> {
     let CompileOptions { env, ref mut shell, jobs, target, spec,
                          dev_deps, features, no_default_features,
-                         lib_only } = *options;
+                         lib_only, ref mut exec_engine } = *options;
+
     let target = target.map(|s| s.to_string());
     let features = features.iter().flat_map(|s| {
         s.as_slice().split(' ')
@@ -149,7 +152,7 @@ pub fn compile_pkg(package: &Package, options: &mut CompileOptions)
         try!(ops::compile_targets(env.as_slice(), targets.as_slice(), to_build,
                                   &PackageSet::new(packages.as_slice()),
                                   &resolve_with_overrides, &sources,
-                                  &config, lib_overrides))
+                                  &config, lib_overrides, exec_engine.clone()))
     };
 
     return Ok(ret);
index f97224b54e577fde9e739fa32ca0aa3a09fa2ea3..0ff3d8760fdfed01b7f47be6c1a5888900893967 100644 (file)
@@ -180,6 +180,7 @@ fn run_verify(pkg: &Package, shell: &mut MultiShell, tar: &Path)
         no_default_features: false,
         spec: None,
         lib_only: false,
+        exec_engine: None,
     }));
 
     Ok(())
index f1d37644366512f0fc427056d3df0c2bcd69ac2e..6293ec800bbd116204c2cf20468f022e28e5ff5b 100644 (file)
@@ -1,6 +1,6 @@
 use std::os;
 
-use ops;
+use ops::{mod, ExecEngine};
 use util::{CargoResult, human, process, ProcessError, ChainError};
 use core::manifest::TargetKind;
 use core::source::Source;
@@ -49,7 +49,8 @@ pub fn run(manifest_path: &Path,
         Some(path) => path,
         None => exe,
     };
-    let process = try!(compile.process(exe, &root))
+    let process = try!(try!(compile.target_process(exe, &root))
+                              .into_process_builder())
                               .args(args)
                               .cwd(try!(os::getcwd()));
 
index 073298670ee538b825cbe9ea7062b7463786252f..af9139a2171934df3e7aa9a7f08907a3f29aafb9 100644 (file)
@@ -5,6 +5,8 @@ use semver::Version;
 use core::{PackageId, Package};
 use util::{mod, CargoResult};
 
+use super::{CommandType, CommandPrototype};
+
 /// A structure returning the result of a compilation.
 pub struct Compilation {
     /// All libraries which were built for a package.
@@ -54,13 +56,35 @@ impl Compilation {
         }
     }
 
+    /// See `process`.
+    pub fn rustc_process(&self, pkg: &Package) -> CargoResult<CommandPrototype> {
+        self.process(CommandType::Rustc, pkg)
+    }
+
+    /// See `process`.
+    pub fn rustdoc_process(&self, pkg: &Package) -> CargoResult<CommandPrototype> {
+        self.process(CommandType::Rustdoc, pkg)
+    }
+
+    /// See `process`.
+    pub fn target_process<T: ToCStr>(&self, cmd: T, pkg: &Package)
+                                     -> CargoResult<CommandPrototype> {
+        self.process(CommandType::Target(cmd.to_c_str()), pkg)
+    }
+
+    /// See `process`.
+    pub fn host_process<T: ToCStr>(&self, cmd: T, pkg: &Package)
+                                   -> CargoResult<CommandPrototype> {
+        self.process(CommandType::Host(cmd.to_c_str()), pkg)
+    }
+
     /// Prepares a new process with an appropriate environment to run against
     /// the artifacts produced by the build process.
     ///
     /// The package argument is also used to configure environment variables as
     /// well as the working directory of the child process.
-    pub fn process<T: ToCStr>(&self, cmd: T, pkg: &Package)
-                              -> CargoResult<util::ProcessBuilder> {
+    pub fn process(&self, cmd: CommandType, pkg: &Package)
+                   -> CargoResult<CommandPrototype> {
         let mut search_path = DynamicLibrary::search_path();
         for dir in self.native_dirs.values() {
             search_path.push(dir.clone());
@@ -69,7 +93,7 @@ impl Compilation {
         search_path.push(self.deps_output.clone());
         let search_path = try!(util::join_paths(search_path.as_slice(),
                                                 DynamicLibrary::envvar()));
-        let mut cmd = try!(util::process(cmd)).env(
+        let mut cmd = try!(CommandPrototype::new(cmd)).env(
             DynamicLibrary::envvar(), Some(search_path.as_slice()));
         for (k, v) in self.extra_env.iter() {
             cmd = cmd.env(k.as_slice(), v.as_ref().map(|s| s.as_slice()));
index 8bcd5d720890a66d29b897773cbf8ebe1ccd9c5b..1a45a0911f91b1a46a8efca83db335b8af441277 100644 (file)
@@ -11,6 +11,7 @@ use super::{Kind, Compilation, BuildConfig};
 use super::TargetConfig;
 use super::layout::{Layout, LayoutProxy};
 use super::custom_build::BuildState;
+use super::{ProcessEngine, ExecEngine};
 
 #[deriving(Show, Copy)]
 pub enum Platform {
@@ -25,6 +26,7 @@ pub struct Context<'a, 'b: 'a> {
     pub sources: &'a SourceMap<'b>,
     pub compilation: Compilation,
     pub build_state: Arc<BuildState>,
+    pub exec_engine: Arc<Box<ExecEngine>>,
 
     env: &'a str,
     host: Layout,
@@ -73,6 +75,7 @@ impl<'a, 'b: 'a> Context<'a, 'b> {
             compilation: Compilation::new(root_pkg),
             build_state: Arc::new(BuildState::new(build_config.clone(), deps)),
             build_config: build_config,
+            exec_engine: Arc::new(box ProcessEngine as Box<ExecEngine>),
         })
     }
 
index f34fb26fd2c00c5971749df1f6cfc64c288c41de..864ebdacaf03b2275b371ea8bb4d5b015a28d449 100644 (file)
@@ -11,6 +11,7 @@ use util::{internal, ChainError};
 
 use super::job::Work;
 use super::{fingerprint, process, Kind, Context, Platform};
+use super::CommandType;
 use util::Freshness;
 
 /// Contains the parsed output of a custom build script.
@@ -49,7 +50,7 @@ pub fn prepare(pkg: &Package, target: &Target, req: Platform,
     // Start preparing the process to execute, starting out with some
     // environment variables.
     let profile = target.get_profile();
-    let mut p = try!(super::process(to_exec, pkg, target, cx))
+    let mut p = try!(super::process(CommandType::Host(to_exec.to_c_str()), pkg, target, cx))
                      .env("OUT_DIR", Some(&build_output))
                      .env("CARGO_MANIFEST_DIR", Some(pkg.get_manifest_path()
                                                         .dir_path()
@@ -101,6 +102,8 @@ pub fn prepare(pkg: &Package, target: &Target, req: Platform,
     try!(fs::mkdir_recursive(&cx.layout(pkg, Kind::Target).build(pkg), USER_RWX));
     try!(fs::mkdir_recursive(&cx.layout(pkg, Kind::Host).build(pkg), USER_RWX));
 
+    let exec_engine = cx.exec_engine.clone();
+
     // Prepare the unit of "dirty work" which will actually run the custom build
     // command.
     //
@@ -136,7 +139,7 @@ pub fn prepare(pkg: &Package, target: &Target, req: Platform,
 
         // And now finally, run the build command itself!
         desc_tx.send_opt(p.to_string()).ok();
-        let output = try!(p.exec_with_output().map_err(|mut e| {
+        let output = try!(exec_engine.exec_with_output(p).map_err(|mut e| {
             e.desc = format!("failed to run custom build command for `{}`\n{}",
                              pkg_name, e.desc);
             Human(e)
diff --git a/src/cargo/ops/cargo_rustc/engine.rs b/src/cargo/ops/cargo_rustc/engine.rs
new file mode 100644 (file)
index 0000000..7b043b4
--- /dev/null
@@ -0,0 +1,138 @@
+use std::collections::HashMap;
+use std::c_str::CString;
+use std::io::process::ProcessOutput;
+use std::fmt::{mod, Show, Formatter};
+
+use util::{mod, CargoResult, ProcessError, ProcessBuilder};
+
+/// Trait for objects that can execute commands.
+pub trait ExecEngine: Send + Sync {
+    fn exec(&self, CommandPrototype) -> Result<(), ProcessError>;
+    fn exec_with_output(&self, CommandPrototype) -> Result<ProcessOutput, ProcessError>;
+}
+
+/// Default implementation of `ExecEngine`.
+#[deriving(Copy)]
+pub struct ProcessEngine;
+
+impl ExecEngine for ProcessEngine {
+    fn exec(&self, command: CommandPrototype) -> Result<(), ProcessError> {
+        command.into_process_builder().unwrap().exec()
+    }
+
+    fn exec_with_output(&self, command: CommandPrototype)
+                        -> Result<ProcessOutput, ProcessError> {
+        command.into_process_builder().unwrap().exec_with_output()
+    }
+}
+
+/// Prototype for a command that must be executed.
+#[deriving(Clone)]
+pub struct CommandPrototype {
+    ty: CommandType,
+    args: Vec<CString>,
+    env: HashMap<String, Option<CString>>,
+    cwd: Path,
+}
+
+impl CommandPrototype {
+    pub fn new(ty: CommandType) -> CargoResult<CommandPrototype> {
+        use std::os;
+
+        Ok(CommandPrototype {
+            ty: ty,
+            args: Vec::new(),
+            env: HashMap::new(),
+            cwd: try!(os::getcwd()),
+        })
+    }
+
+    pub fn get_type(&self) -> &CommandType {
+        &self.ty
+    }
+
+    pub fn arg<T: ToCStr>(mut self, arg: T) -> CommandPrototype {
+        self.args.push(arg.to_c_str());
+        self
+    }
+
+    pub fn args<T: ToCStr>(mut self, arguments: &[T]) -> CommandPrototype {
+        self.args.extend(arguments.iter().map(|t| t.to_c_str()));
+        self
+    }
+
+    pub fn get_args(&self) -> &[CString] {
+        self.args.as_slice()
+    }
+
+    pub fn cwd(mut self, path: Path) -> CommandPrototype {
+        self.cwd = path;
+        self
+    }
+
+    pub fn get_cwd(&self) -> &Path {
+        &self.cwd
+    }
+
+    pub fn env<T: ToCStr>(mut self, key: &str, val: Option<T>) -> CommandPrototype {
+        self.env.insert(key.to_string(), val.map(|t| t.to_c_str()));
+        self
+    }
+
+    pub fn get_envs(&self) -> &HashMap<String, Option<CString>> {
+        &self.env
+    }
+
+    pub fn into_process_builder(self) -> CargoResult<ProcessBuilder> {
+        let mut builder = try!(match self.ty {
+            CommandType::Rustc => util::process("rustc"),
+            CommandType::Rustdoc => util::process("rustdoc"),
+            CommandType::Target(ref cmd) | CommandType::Host(ref cmd) => {
+                util::process(cmd.as_bytes_no_nul())
+            },
+        });
+
+        for arg in self.args.into_iter() {
+            builder = builder.arg(arg.as_bytes_no_nul());
+        }
+
+        for (key, val) in self.env.into_iter() {
+            builder = builder.env(key.as_slice(), val.as_ref().map(|v| v.as_bytes_no_nul()));
+        }
+
+        builder = builder.cwd(self.cwd);
+
+        Ok(builder)
+    }
+}
+
+impl Show for CommandPrototype {
+    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+        match self.ty {
+            CommandType::Rustc => try!(write!(f, "`rustc")),
+            CommandType::Rustdoc => try!(write!(f, "`rustdoc")),
+            CommandType::Target(ref cmd) | CommandType::Host(ref cmd) => {
+                let cmd = String::from_utf8_lossy(cmd.as_bytes_no_nul());
+                try!(write!(f, "`{}", cmd));
+            },
+        }
+
+        for arg in self.args.iter() {
+            try!(write!(f, " {}", String::from_utf8_lossy(arg.as_bytes_no_nul())));
+        }
+
+        write!(f, "`")
+    }
+}
+
+#[deriving(Clone, Show)]
+pub enum CommandType {
+    Rustc,
+    Rustdoc,
+
+    /// The command is to be executed for the target architecture.
+    Target(CString),
+
+    /// The command is to be executed for the host architecture.
+    Host(CString),
+}
index b31d77d2019c837a757725e8e5a868d8f9f344f4..c8d4bcd85047ed5786f8431031c0626db24fff33 100644 (file)
@@ -2,9 +2,10 @@ use std::collections::{HashSet, HashMap};
 use std::dynamic_lib::DynamicLibrary;
 use std::io::{fs, USER_RWX};
 use std::io::fs::PathExtensions;
+use std::sync::Arc;
 
 use core::{SourceMap, Package, PackageId, PackageSet, Target, Resolve};
-use util::{mod, CargoResult, ProcessBuilder, human, caused_human};
+use util::{mod, CargoResult, human, caused_human};
 use util::{Config, internal, ChainError, Fresh, profile, join_paths, Human};
 
 use self::job::{Job, Work};
@@ -13,12 +14,14 @@ use self::job_queue::{JobQueue, Stage};
 pub use self::compilation::Compilation;
 pub use self::context::Context;
 pub use self::context::Platform;
+pub use self::engine::{CommandPrototype, CommandType, ExecEngine, ProcessEngine};
 pub use self::layout::{Layout, LayoutProxy};
 pub use self::custom_build::BuildOutput;
 
 mod context;
 mod compilation;
 mod custom_build;
+mod engine;
 mod fingerprint;
 mod job;
 mod job_queue;
@@ -112,7 +115,8 @@ pub fn compile_targets<'a>(env: &str, targets: &[&'a Target], pkg: &'a Package,
                            deps: &PackageSet, resolve: &'a Resolve,
                            sources: &'a SourceMap,
                            config: &'a Config<'a>,
-                           build_config: BuildConfig)
+                           build_config: BuildConfig,
+                           exec_engine: Option<Arc<Box<ExecEngine>>>)
                            -> CargoResult<Compilation> {
     if targets.is_empty() {
         return Ok(Compilation::new(pkg))
@@ -136,6 +140,10 @@ pub fn compile_targets<'a>(env: &str, targets: &[&'a Target], pkg: &'a Package,
     let mut cx = try!(Context::new(env, resolve, sources, deps, config,
                                    host_layout, target_layout, pkg,
                                    build_config));
+    if let Some(exec_engine) = exec_engine {
+        cx.exec_engine = exec_engine.clone();
+    }
+
     let mut queue = JobQueue::new(cx.resolve, deps, cx.config);
 
     // First ensure that the destination directory exists
@@ -365,7 +373,8 @@ fn compile_custom_old(pkg: &Package, cmd: &str,
     //       may be building a C lib for a plugin
     let layout = cx.layout(pkg, Kind::Target);
     let output = layout.native(pkg);
-    let mut p = try!(process(cmd.next().unwrap(), pkg, target, cx))
+    let mut p = try!(process(CommandType::Host(cmd.next().unwrap().to_c_str()), pkg,
+                             target, cx))
                      .env("OUT_DIR", Some(&output))
                      .env("DEPS_DIR", Some(&output))
                      .env("TARGET", Some(cx.target_triple()))
@@ -400,6 +409,8 @@ fn compile_custom_old(pkg: &Package, cmd: &str,
     }
     let pkg = pkg.to_string();
 
+    let exec_engine = cx.exec_engine.clone();
+
     Ok(Work::new(move |desc_tx: Sender<String>| {
         desc_tx.send_opt(p.to_string()).ok();
         if first && !output.exists() {
@@ -407,7 +418,7 @@ fn compile_custom_old(pkg: &Package, cmd: &str,
                 internal("failed to create output directory for build command")
             }))
         }
-        try!(p.exec_with_output().map(|_| ()).map_err(|mut e| {
+        try!(exec_engine.exec_with_output(p).map(|_| ()).map_err(|mut e| {
             e.desc = format!("Failed to run custom build command for `{}`\n{}",
                              pkg, e.desc);
             Human(e)
@@ -428,6 +439,7 @@ fn rustc(package: &Package, target: &Target,
         let show_warnings = package.get_package_id() == cx.resolve.root() ||
                             is_path_source;
         let rustc = if show_warnings {rustc} else {rustc.arg("-Awarnings")};
+        let exec_engine = cx.exec_engine.clone();
 
         let filenames = try!(cx.target_filenames(target));
         let root = cx.out_dir(package, kind, target);
@@ -505,7 +517,7 @@ fn rustc(package: &Package, target: &Target,
             }
 
             desc_tx.send_opt(rustc.to_string()).ok();
-            try!(rustc.exec().chain_error(|| {
+            try!(exec_engine.exec(rustc).chain_error(|| {
                 human(format!("Could not compile `{}`.", name))
             }));
 
@@ -519,8 +531,8 @@ fn rustc(package: &Package, target: &Target,
 
 fn prepare_rustc(package: &Package, target: &Target, crate_types: Vec<&str>,
                  cx: &Context, req: Platform)
-                 -> CargoResult<Vec<(ProcessBuilder, Kind)>> {
-    let base = try!(process("rustc", package, target, cx));
+                 -> CargoResult<Vec<(CommandPrototype, Kind)>> {
+    let base = try!(process(CommandType::Rustc, package, target, cx));
     let base = build_base_args(cx, base, package, target, crate_types.as_slice());
 
     let target_cmd = build_plugin_args(base.clone(), cx, package, target, Kind::Target);
@@ -546,7 +558,8 @@ fn rustdoc(package: &Package, target: &Target,
     let kind = Kind::Target;
     let pkg_root = package.get_root();
     let cx_root = cx.layout(package, kind).proxy().dest().join("doc");
-    let rustdoc = try!(process("rustdoc", package, target, cx)).cwd(pkg_root.clone());
+    let rustdoc = try!(process(CommandType::Rustdoc, package, target, cx))
+                  .cwd(pkg_root.clone());
     let mut rustdoc = rustdoc.arg(target.get_src_path())
                          .arg("-o").arg(cx_root)
                          .arg("--crate-name").arg(target.get_name());
@@ -573,14 +586,16 @@ fn rustdoc(package: &Package, target: &Target,
     let primary = package.get_package_id() == cx.resolve.root();
     let name = package.get_name().to_string();
     let desc = rustdoc.to_string();
+    let exec_engine = cx.exec_engine.clone();
+
     Ok(Work::new(move |desc_tx: Sender<String>| {
         desc_tx.send(desc);
         if primary {
-            try!(rustdoc.exec().chain_error(|| {
+            try!(exec_engine.exec(rustdoc).chain_error(|| {
                 human(format!("Could not document `{}`.", name))
             }))
         } else {
-            try!(rustdoc.exec_with_output().and(Ok(())).map_err(|err| {
+            try!(exec_engine.exec_with_output(rustdoc).and(Ok(())).map_err(|err| {
                 match err.exit {
                     Some(..) => {
                         caused_human(format!("Could not document `{}`.",
@@ -597,10 +612,10 @@ fn rustdoc(package: &Package, target: &Target,
 }
 
 fn build_base_args(cx: &Context,
-                   mut cmd: ProcessBuilder,
+                   mut cmd: CommandPrototype,
                    pkg: &Package,
                    target: &Target,
-                   crate_types: &[&str]) -> ProcessBuilder {
+                   crate_types: &[&str]) -> CommandPrototype {
     let metadata = target.get_metadata();
 
     // TODO: Handle errors in converting paths into args
@@ -680,16 +695,16 @@ fn build_base_args(cx: &Context,
 }
 
 
-fn build_plugin_args(mut cmd: ProcessBuilder, cx: &Context, pkg: &Package,
-                     target: &Target, kind: Kind) -> ProcessBuilder {
+fn build_plugin_args(mut cmd: CommandPrototype, cx: &Context, pkg: &Package,
+                     target: &Target, kind: Kind) -> CommandPrototype {
     cmd = cmd.arg("--out-dir");
     cmd = cmd.arg(cx.out_dir(pkg, kind, target));
 
     cmd = cmd.arg("--emit=dep-info,link");
 
     if kind == Kind::Target {
-        fn opt(cmd: ProcessBuilder, key: &str, prefix: &str,
-               val: Option<&str>) -> ProcessBuilder {
+        fn opt(cmd: CommandPrototype, key: &str, prefix: &str,
+               val: Option<&str>) -> CommandPrototype {
             match val {
                 Some(val) => {
                     cmd.arg(key)
@@ -707,9 +722,9 @@ fn build_plugin_args(mut cmd: ProcessBuilder, cx: &Context, pkg: &Package,
     return cmd;
 }
 
-fn build_deps_args(mut cmd: ProcessBuilder, target: &Target, package: &Package,
+fn build_deps_args(mut cmd: CommandPrototype, target: &Target, package: &Package,
                    cx: &Context,
-                   kind: Kind) -> CargoResult<ProcessBuilder> {
+                   kind: Kind) -> CargoResult<CommandPrototype> {
     let layout = cx.layout(package, kind);
     cmd = cmd.arg("-L").arg(layout.root());
     cmd = cmd.arg("-L").arg(layout.deps());
@@ -749,8 +764,8 @@ fn build_deps_args(mut cmd: ProcessBuilder, target: &Target, package: &Package,
 
     return Ok(cmd);
 
-    fn link_to(mut cmd: ProcessBuilder, pkg: &Package, target: &Target,
-               cx: &Context, kind: Kind) -> CargoResult<ProcessBuilder> {
+    fn link_to(mut cmd: CommandPrototype, pkg: &Package, target: &Target,
+               cx: &Context, kind: Kind) -> CargoResult<CommandPrototype> {
         // If this target is itself a plugin *or* if it's being linked to a
         // plugin, then we want the plugin directory. Otherwise we want the
         // target directory (hence the || here).
@@ -773,8 +788,8 @@ fn build_deps_args(mut cmd: ProcessBuilder, target: &Target, package: &Package,
     }
 }
 
-pub fn process<T: ToCStr>(cmd: T, pkg: &Package, target: &Target,
-                          cx: &Context) -> CargoResult<ProcessBuilder> {
+pub fn process(cmd: CommandType, pkg: &Package, target: &Target,
+               cx: &Context) -> CargoResult<CommandPrototype> {
     // When invoking a tool, we need the *host* deps directory in the dynamic
     // library search path for plugins and such which have dynamic dependencies.
     let layout = cx.layout(pkg, Kind::Host);
index 5181b3642783b1fc0cf4866032aaf60c870c7c60..888538a32ec17e4acb28c7beb22f9933a63698a1 100644 (file)
@@ -2,7 +2,7 @@ use std::os;
 
 use core::Source;
 use sources::PathSource;
-use ops;
+use ops::{mod, ExecEngine, ProcessEngine};
 use util::{CargoResult, ProcessError};
 
 pub struct TestOptions<'a> {
@@ -32,14 +32,15 @@ pub fn run_tests(manifest_path: &Path,
             Some(path) => path,
             None => exe.clone(),
         };
-        let cmd = try!(compile.process(exe, &compile.package)).args(test_args);
+        let cmd = try!(compile.target_process(exe, &compile.package))
+                  .args(test_args);
         try!(options.compile_opts.shell.concise(|shell| {
             shell.status("Running", to_display.display().to_string())
         }));
         try!(options.compile_opts.shell.verbose(|shell| {
             shell.status("Running", cmd.to_string())
         }));
-        match cmd.exec() {
+        match ExecEngine::exec(&mut ProcessEngine, cmd) {
             Ok(()) => {}
             Err(e) => return Ok(Some(e))
         }
@@ -58,7 +59,7 @@ pub fn run_tests(manifest_path: &Path,
 
     for (lib, name) in libs {
         try!(options.compile_opts.shell.status("Doc-tests", name));
-        let mut p = try!(compile.process("rustdoc", &compile.package))
+        let mut p = try!(compile.rustdoc_process(&compile.package))
                            .arg("--test").arg(lib)
                            .arg("--crate-name").arg(name)
                            .arg("-L").arg(&compile.root_output)
@@ -82,7 +83,7 @@ pub fn run_tests(manifest_path: &Path,
         try!(options.compile_opts.shell.verbose(|shell| {
             shell.status("Running", p.to_string())
         }));
-        match p.exec() {
+        match ExecEngine::exec(&mut ProcessEngine, p) {
             Ok(()) => {}
             Err(e) => return Ok(Some(e)),
         }
index 53ade356e9f55c2843a526eb5ace5c27a1fa389c..ae28b4befc2aabe295d2c45c0ba1b181e23f931f 100644 (file)
@@ -5,6 +5,7 @@ pub use self::cargo_rustc::{compile_targets, Compilation, Layout, Kind, rustc_ve
 pub use self::cargo_rustc::{Context, LayoutProxy};
 pub use self::cargo_rustc::Platform;
 pub use self::cargo_rustc::{BuildOutput, BuildConfig, TargetConfig};
+pub use self::cargo_rustc::{CommandType, CommandPrototype, ExecEngine, ProcessEngine};
 pub use self::cargo_run::run;
 pub use self::cargo_new::{new, NewOptions};
 pub use self::cargo_doc::{doc, DocOptions};